package com.ibm.cps.sql.netsfparser;

import java.util.List;

import com.ibm.cps.sql.AggregationDescriptor.WindowType;
import com.ibm.cps.sql.window.WindowDescriptor;

import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.ExpressionVisitorAdapter;
import net.sf.jsqlparser.expression.Function;
import net.sf.jsqlparser.schema.Column;

public class GroupByKeyParser extends ExpressionVisitorAdapter {
	private WindowDescriptor window;
	private String aggregationField;

	public WindowDescriptor getWindow() {
		return window;
	}

	public String getAggregationField() {
		return aggregationField;
	}

	@Override
	public void visit(Function arg0) {
		String functionName = arg0.getName().toUpperCase();
		List<Expression> windowArguments = arg0.getParameters().getExpressions();
		WindowArguments arguments = parseWindowArguments(windowArguments);
		if(functionName.equals("TIMEWINDOW")){
			this.window = new WindowDescriptor(WindowType.TIME, arguments.size, arguments.interval);
		}else if(functionName.equals("COUNTWINDOW")){
			this.window = new WindowDescriptor(WindowType.COUNT, arguments.size, arguments.interval);
		}else{
			throw new IllegalArgumentException("unexpected sliding window type: " + functionName + " must be either TimeWindow or CountWindow");
		}

	}

	private WindowArguments parseWindowArguments(List<Expression> argumentExpressions){
		int argumentCount = argumentExpressions.size();
		if(argumentCount < 1 && argumentCount > 2)
			throw new IllegalArgumentException("Window parameter must be specified, e.g. <window_type>(windowLength, windowInterval), or <window_type>(WindowLength)");
		try{
			long size = Long.parseLong(argumentExpressions.get(0).toString());
			long interval = 1;
			if(argumentCount == 2){
				interval = Long.parseLong(argumentExpressions.get(1).toString());
			}
			return new WindowArguments(size, interval);
		}catch(RuntimeException ex){
			throw new IllegalArgumentException("Illegal window parameter, parameter must be an long value");
		}
	}

	private static class WindowArguments{
		private final long size;
		private final long interval;

		public WindowArguments(long length, long interval) {
			this.size = length;
			this.interval = interval;
		}

		@Override
		public String toString() {
			return "{\"WindowArguments\":{\"length\":\"" + size
					+ "\", \"interval\":\"" + interval + "\"}}";
		}
	}

	@Override
	public void visit(Column arg0) {
		this.aggregationField = arg0.getFullyQualifiedName();
	}

}
